<template>
  <div class="app-container">
    <!-- 搜索 -->
    <el-form inline>
      <el-form-item>
        <el-input v-model="tempSearchObj.username" placeholder="用户名" />
      </el-form-item>
      <el-button type="primary" icon="el-icon-search" @click="search"
        >查询</el-button
      >
      <el-button type="default" @click="resetSearch">清空</el-button>
    </el-form>

    <!-- 添加删除 -->
    <div style="margin-bottom: 20px">
      <el-button
        type="primary"
        @click="showAddUser"
        v-if="$hasBP('btn.User.add')"
        >添 加</el-button
      >
      <el-button
        type="danger"
        @click="revomveUsers"
        :disabled="selectedIds.length === 0"
        v-if="$hasBP('btn.User.remove')"
        >批量删除</el-button
      >
    </div>
    <!-- 主体 -->
    <el-table
      border
      stripe
      v-loading="listLoading"
      element-loading-text="玩命加载中，网络太垃圾了，赶紧换个宽带！！"
      element-loading-spinner="el-icon-loading"
      element-loading-background="rgba(0, 0, 0, 0.8)"
      :data="users"
      @selection-change="handleSelectionChange"
    >
      <!-- 复选框 -->
      <el-table-column type="selection" width="55" fixed="left" />

      <el-table-column prop="username" label="用户名" width="150" />
      <el-table-column prop="nickName" label="用户昵称" width="150" />
      <el-table-column prop="roleName" label="角色列表" width="150" />
      <el-table-column prop="gmtCreate" label="创建时间" width="180" />
      <el-table-column prop="gmtModified" label="更新时间" width="180" />
      <!-- 操作 -->
      <el-table-column label="操作" width="230" align="center" fixed="right">
        <!-- 按钮 -->
        <template slot-scope="{ row }">
          <HintButton
            type="info"
            size="mini"
            icon="el-icon-user-solid"
            title="分配角色"
            v-if="$hasBP('btn.User.assgin')"
            @click="showAssignRole(row)"
          />
          <HintButton
            type="primary"
            size="mini"
            icon="el-icon-edit"
            title="修改用户"
            v-if="$hasBP('btn.User.update')"
            @click="showUpdateUser(row)"
          />
          <el-popconfirm
            :title="`确定删除 ${row.username} 吗?`"
            @onConfirm="removeUser(row.id)"
          >
            <HintButton
              style="margin-left:10px"
              slot="reference"
              type="danger"
              size="mini"
              icon="el-icon-delete"
              title="删除用户"
              v-if="$hasBP('btn.User.remove')"
            />
          </el-popconfirm>
        </template>
      </el-table-column>
    </el-table>

    <!-- 分页器 -->
    <el-pagination
      :current-page="page"
      :total="total"
      :page-size="limit"
      :page-sizes="[3, 5, 7, 9]"
      style="padding: 20px 0;"
      layout="prev, pager, next, jumper, ->, sizes, total"
      @current-change="getUsers"
      @size-change="handleSizeChange"
    />

    <!-- 添加修改 -->
    <el-dialog
      :title="user.id ? '修改用户' : '添加用户'"
      :visible.sync="dialogUserVisible"
    >
      <el-form
        ref="userForm"
        :model="user"
        :rules="userRules"
        label-width="120px"
      >
        <el-form-item label="用户名" prop="username">
          <el-input v-model="user.username" />
        </el-form-item>
        <el-form-item label="用户昵称">
          <el-input v-model="user.nickName" />
        </el-form-item>

        <el-form-item v-if="!user.id" label="用户密码" prop="password">
          <el-input v-model="user.password" />
        </el-form-item>
      </el-form>
      <div slot="footer" class="dialog-footer">
        <el-button @click="cancel">取 消</el-button>
        <el-button :loading="loading" type="primary" @click="addOrUpdate"
          >确 定</el-button
        >
      </div>
    </el-dialog>

    <!-- 设置角色 -->
    <el-dialog
      title="设置角色"
      :visible.sync="dialogRoleVisible"
      :before-close="resetRoleData"
    >
      <el-form label-width="80px">
        <el-form-item label="用户名">
          <el-input disabled :value="user.username"></el-input>
        </el-form-item>

        <el-form-item label="角色列表">
          <el-checkbox
            :indeterminate="isIndeterminate"
            v-model="checkAll"
            @change="handleCheckAllChange"
            >全选</el-checkbox
          >
          <div style="margin: 15px 0;"></div>
          <el-checkbox-group
            v-model="userRoleIds"
            @change="handleCheckedChange"
          >
            <el-checkbox
              v-for="role in allRoles"
              :key="role.id"
              :label="role.id"
              >{{ role.roleName }}</el-checkbox
            >
          </el-checkbox-group>
        </el-form-item>
      </el-form>
      <div slot="footer">
        <el-button :loading="loading" type="primary" @click="assignRole"
          >保存</el-button
        >
        <el-button @click="resetRoleData">取消</el-button>
      </div>
    </el-dialog>
  </div>
</template>

<script>
export default {
  name: "AclUserList",
  data() {
    return {
      listLoading: false, //加载提示
      //搜索条件的数据对象
      searchObj: {
        username: ""
      },
      //搜索输入的对象
      tempSearchObj: {
        username: ""
      },
      selectedIds: [], //所有选则的user的id的数组
      users: [], // 当前用户列表
      page: 1, // 当前页码
      limit: 5, // 每页数量
      total: 0, // 总数量
      user: {}, // 当前要操作的user
      dialogUserVisible: false, //是否显示添加或修改的对话框
      // 添加或修改的表单校验规则
      userRules: {
        username: [
          { required: true, message: "用户名必须输入" },
          { min: 4, message: "用户名不能小于4位" }
        ],
        password: [{ required: true, validator: this.validatePassword }]
      },
      loading: false, // 是否正在提交请求中
      dialogRoleVisible: false, // 是否显示角色对话框
      allRoles: [], // 全部角色列表
      userRoleIds: [], // 用户角色ID列表
      isIndeterminate: false, // 是否是不确定
      checkAll: false // 是否全选
    };
  },

  created() {
    this.getUsers();
  },

  // 定义方法
  methods: {
    // 显示某个角色的界面
    showAssignRole(user) {
      this.user = user;
      this.dialogRoleVisible = true;
      this.getRoles();
    },

    // 勾选状态发生改变的监听(当前勾选状态)
    handleCheckAllChange(value) {
      // 如果是全选，userRoleIds就是所有角色id的数组
      this.userRoleIds = value ? this.allRoles.map(item => item.id) : [];
      // 既不是全选也不是不选，指定为false
      this.isIndeterminate = false;
    },

    // 异步获取用户角色列表
    async getRoles() {
      const result = await this.$API.user.getRoles(this.user.id);
      const { allRolesList, assignRoles } = result.data;
      this.allRoles = allRolesList;
      this.userRoleIds = assignRoles.map(item => item.id);
      this.checkAll = allRolesList.length === assignRoles.length;
      this.isIndeterminate =
        assignRoles.length > 0 && assignRoles.length < allRolesList.length;
    },

    // 角色列表选中项发生改变的监听
    handleCheckedChange(value) {
      const { userRoleIds, allRoles } = this;
      this.checkAll =
        userRoleIds.length === allRoles.length && allRoles.length > 0;
      this.isIndeterminate =
        userRoleIds.length > 0 && userRoleIds.length < allRoles.length;
    },

    //请求给用户角色授权
    async assignRole() {
      const userId = this.user.id;
      const roleIds = this.userRoleIds.join(",");
      this.loading = true;
      const result = await this.$API.user.assignRoles(userId, roleIds);
      this.loading = false;
      this.$message.success(result.message || "分配角色成功");
      this.resetRoleData();
      if (this.$store.getters.name === this.user.username) {
        window.location.reload();
      }
    },

    // 重置用户角色数据
    resetRoleData() {
      this.dialogRoleVisible = false;
      this.allRoles = [];
      thsi.userRoleIds = [];
      this.isIndeterminate = false;
      this.checkAll = false;
    },

    // 密码校验
    validatePassword(rule, value, callback) {
      if (!value) {
        callback("必须输入密码");
      } else if (!value || value.length < 6) {
        callback("密码长度不能小于6位");
      } else {
        callback();
      }
    },

    // 根据输入搜索
    search() {
      this.searchObj = { ...this.tempSearchObj };
      this.getUsers();
    },

    // 清空输入
    resetSearch() {
      this.searchObj = {
        username: ""
      };
      this.tempSearchObj = {
        username: ""
      };
      this.getUsers();
    },

    // 显示添加用户的对话框
    showAddUser() {
      this.user = {};
      this.dialogUserVisible = true;
      this.$nextTick(() => this.$refs.userForm.clearValidate());
    },

    // 删除所有选中的用户
    revomveUsers() {
      this.$confirm("确定删除吗?")
        .then(async () => {
          const result = await this.$API.user.removeUsers(this.selectedIds);
          this.$message.success("删除成功");
          this.getUsers();
        })
        .catch(() => {
          this.$message.info("取消删除");
        });
    },

    // 列表选中状态发生改变的监听回调
    handleSelectionChange(selection) {
      this.selectedIds = selection.map(item => item.id);
    },

    // 显示更新用户的界面
    showUpdateUser(user) {
      this.user = { ...user };
      this.dialogUserVisible = true;
    },

    // 删除某个用户
    async removeUser(id) {
      await this.$API.user.removeById(id);
      this.$message.success("删除成功");
      this.getUsers(this.users.length === 1 ? this.page - 1 : this.page);
    },

    // 获取分页列表
    async getUsers(page = 1) {
      this.page = page;
      const { limit, searchObj } = this;
      this.listLoading = true;
      const result = await this.$API.user.getPageList(page, limit, searchObj);
      this.listLoading = false;
      const { items, total } = result.data;
      this.users = items.filter(item => item.username !== "admin");
      this.total = total - 1;
      this.selectedIds = [];
    },

    // 处理pageSize改变的监听
    handleSizeChange(pageSize) {
      this.limit = pageSize;
      this.getUsers();
    },

    // 取消保存或更新
    cancel() {
      this.dialogUserVisible = false;
      this.user = {};
    },

    // 保存或更新用户
    addOrUpdate() {
      this.$refs.userForm.validate(valid => {
        if (valid) {
          const { user } = this;
          if (user.username === "admin") {
            alert("admin账号不能添加或更新");
            return;
          }
          this.loading = true;
          this.$API.user[user.id ? "update" : "add"](user).then(() => {
            this.loading = false;
            this.$message.success("保存成功!");
            this.getUsers(user.id ? this.page : 1);
            this.user = {};
            this.dialogUserVisible = false;
          });
        }
      });
    }
  }
};
</script>

<style scoped></style>
